import * as THREE from 'three'
import {
    OrbitControls
} from 'three/examples/jsm/controls/OrbitControls.js'
import {
    RGBELoader
} from 'three/examples/jsm/loaders/RGBELoader'
import * as dat from 'dat.gui'
import ALPHA from './assets/mesh/alpha.jpg'
import ROUGHNESS from './assets/mesh/roughness.jpg'
import METALNESS from './assets/mesh/metalness.jpg'
import NORMAL from './assets/mesh/normal.jpg'
import DISPLACEMENT from './assets/mesh/displacement.jpg'
import BG from './assets/mesh/1.jpg'
import HDR from './assets/mesh/ballroom_4k.hdr'
import {
    MeshBasicMaterial
} from 'three'

const scene = new THREE.Scene();
// 相机 （透视相机）  角度、宽高比、近端面、远端面
const camera = new THREE.PerspectiveCamera(75, window.innerWidth / window.innerHeight, 0.1, 1000);
camera.position.set(0, 0, 5);
scene.add(camera);

const textureLoader = new THREE.CubeTextureLoader()
// const envMap = textureLoader.load(BG)
// const envMap = textureLoader.load([ALPHA, ROUGHNESS, METALNESS, NORMAL, DISPLACEMENT, NORMAL])
// 加载HDR
const rgbeloader = new RGBELoader()
// rgbeloader.loadAsync(HDR).then((texture) => {
//     texture.mapping = THREE.EquirectangularReflectionMapping
//     scene.background = texture
//     scene.environment = texture
// })

// 标准网格材质
const geometry = new THREE.SphereGeometry(1, 20, 20);
const meshStandardMaterial = new THREE.MeshStandardMaterial({
    // 粗糙度
    // roughness: 0.1,
    // 金属
    // metalness: 0.7,
    // envMap: envMap
});
const cube = new THREE.Mesh(geometry, meshStandardMaterial);
// 物体阴影投射
cube.castShadow = true
scene.add(cube);

// 添加底部平面
const planeGeometry = new THREE.PlaneGeometry(50, 50)
const plane = new THREE.Mesh(planeGeometry, meshStandardMaterial)
plane.position.set(0, -2, 0)
plane.rotation.x = -Math.PI / 2
// 平面接收阴影
plane.receiveShadow = true
scene.add(plane)

// 给场景加背景和设置球体的环境贴图
// scene.background = envMap
// scene.environment = envMap

// 灯光
const light = new THREE.AmbientLight(0xffffff, 1);
scene.add(light);
// // 平行光
// const directionalLight = new THREE.DirectionalLight(0xffffff, 1);
// directionalLight.position.set(-10, 10, 10)
// // 开启直线光阴影
// directionalLight.castShadow = true
// // 阴影模糊度
// directionalLight.shadow.radius = 20
// // 阴影贴图分辨率
// directionalLight.shadow.mapSize.set(2048, 2048)
// // 相机远近端
// directionalLight.shadow.camera.near = 17
// directionalLight.shadow.camera.far = 500
// directionalLight.shadow.camera.top = 5
// directionalLight.shadow.camera.bottom = -5
// directionalLight.shadow.camera.left = -5
// directionalLight.shadow.camera.right = 5
// scene.add(directionalLight);

// 聚光灯
const spotlight = new THREE.SpotLight(0xffffff, 1);
spotlight.position.set(5, 10, 5)
// 开启直线光阴影
spotlight.castShadow = true
// 阴影模糊度
spotlight.shadow.radius = 20
// 阴影贴图分辨率
spotlight.shadow.mapSize.set(4096, 4096)
// 设置聚光灯的目标 无论目标物体如何移动都会照在目标上
spotlight.target = cube
// 聚光灯角度
spotlight.angle = Math.PI / 6
// 聚光灯光强衰减
spotlight.distance = 20
// 聚光灯光半阴影衰减
spotlight.penumbra = 0
// 聚光灯 光距离衰减
spotlight.decay = 0
// scene.add(spotlight);


// 
const smallBox = new THREE.Mesh(
    new THREE.SphereGeometry(0.1, 20, 20),
    new THREE.MeshBasicMaterial({
        color: 0xff0000
    })
)
smallBox.position.set(2, 2, 2)

// 点光源
const pointLight = new THREE.PointLight(0xff0000, 1);
pointLight.position.set(2, 2, 2)
pointLight.castShadow = true
pointLight.shadow.radius = 20
pointLight.shadow.mapSize.set(4096, 4096)
spotlight.distance = 10
pointLight.decay = 1
// scene.add(pointLight)
smallBox.add(pointLight)
scene.add(smallBox)

// 坐标轴辅助器
const axesHelper = new THREE.AxesHelper(5);
scene.add(axesHelper);

// 渲染
const renderer = new THREE.WebGLRenderer();
renderer.setSize(window.innerWidth, window.innerHeight);
// 开启阴影贴图
renderer.shadowMap.enabled = true
// 物理上的光照模式
renderer.physicallyCorrectLights = true
document.body.appendChild(renderer.domElement);

// 新增轨迹控制器
const controls = new OrbitControls(camera, renderer.domElement);

const clock = new THREE.Clock()

// 使用渲染器   通过相机将场景渲染
function render() {
    const time = clock.getElapsedTime()
    smallBox.position.x = Math.sin(time) * 3
    smallBox.position.z = Math.cos(time) * 3
    smallBox.position.y = 2 + Math.sin(time * 3)
    renderer.render(scene, camera);
    requestAnimationFrame(render);
}

render()

const GUI = new dat.GUI();
// GUI.add(directionalLight.shadow.camera, 'near').min(17).max(19).step(0.01).name('灯光拉近')
//     .onChange(() => {
//         directionalLight.shadow.camera.updateProjectionMatrix()
//     })
GUI.add(cube.position, 'x').min(-20).max(20).step(0.01).name('x')
GUI.add(spotlight, 'angle').min(0).max(Math.PI / 2).step(0.01).name('angle')
GUI.add(spotlight, 'distance').min(10).max(30).step(0.01).name('distance')
GUI.add(spotlight, 'penumbra').min(0).max(1).step(0.01).name('penumbra')
GUI.add(spotlight, 'decay').min(0).max(5).step(0.01).name('decay')